// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////

var StringMap = flame.internal.StringMap;

function StringMapTest() {
  this.map_ = new StringMap();
};
registerTestSuite(StringMapTest);

//////////////////////////////////////////////////////
// Tests
//////////////////////////////////////////////////////

StringMapTest.prototype.WrongTypes = function() {
  var map = this.map_;
  var insert = function(item) { return function() { map.insert(item, 1); } };
  var get = function(item) { return function() { map.get(item); } };
  var contains = function(item) { return function() { map.contains(item); } };

  var expected = /TypeError.* must be a string/;

  expectThat(insert(), throwsError(expected));
  expectThat(insert(undefined), throwsError(expected));
  expectThat(insert(17), throwsError(expected));
  expectThat(insert(true), throwsError(expected));

  expectThat(get(), throwsError(expected));
  expectThat(get(undefined), throwsError(expected));
  expectThat(get(17), throwsError(expected));
  expectThat(get(true), throwsError(expected));

  expectThat(contains(), throwsError(expected));
  expectThat(contains(undefined), throwsError(expected));
  expectThat(contains(17), throwsError(expected));
  expectThat(contains(true), throwsError(expected));
};

StringMapTest.prototype.NoElements = function() {
  var map = this.map_;

  expectFalse(map.contains(''));
  expectFalse(map.contains('taco'));

  expectThat(function() { map.get('') }, throwsError(/Unknown key/));
  expectThat(function() { map.get('taco') },
             throwsError(/Unknown key.*taco/));

  expectThat(map.getKeys(), elementsAre([]));
};

StringMapTest.prototype.OneElement = function() {
  var map = this.map_;

  map.insert('taco', 17);

  expectTrue(map.contains('taco'));
  expectFalse(map.contains(''));
  expectFalse(map.contains('burrito'));

  expectThat(function() { map.get('') }, throwsError(/Unknown key/));
  expectThat(function() { map.get('burrito') },
             throwsError(/Unknown key.*burrito/));

  expectEq(17, map.get('taco'));
  expectThat(map.getKeys(), elementsAre(['taco']));
};

StringMapTest.prototype.MultipleElements = function() {
  var map = this.map_;

  map.insert('taco', 17);
  map.insert('burrito', 19);
  map.insert('enchilada', undefined);

  expectTrue(map.contains('taco'));
  expectTrue(map.contains('burrito'));
  expectTrue(map.contains('enchilada'));
  expectFalse(map.contains(''));

  expectThat(function() { map.get('queso') },
             throwsError(/Unknown key.*queso/));

  var elements = map.getKeys();
  expectThat(elements, elementsAre([_, _, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('burrito'));
  expectThat(elements, contains('enchilada'));

  expectEq(17, map.get('taco'));
  expectEq(19, map.get('burrito'));
  expectEq(undefined, map.get('enchilada'));
};

StringMapTest.prototype.InsertThenUpdate = function() {
  var map = this.map_;

  map.insert('taco', 17);
  map.insert('burrito', 19);
  map.insert('taco', 23);

  expectTrue(map.contains('taco'));
  expectTrue(map.contains('burrito'));

  var elements = map.getKeys();
  expectThat(elements, elementsAre([_, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('burrito'));

  expectEq(23, map.get('taco'));
  expectEq(19, map.get('burrito'));
};

StringMapTest.prototype.SpecialKeys = function() {
  var map = this.map_;

  expectFalse(map.contains(''));
  expectFalse(map.contains('_'));
  expectFalse(map.contains('constructor'));
  expectFalse(map.contains('hasOwnProperty'));
  expectFalse(map.contains('prototype'));
  expectFalse(map.contains('김치'));

  map.insert('', 17);
  map.insert('_', 19);
  map.insert('constructor', 23);
  map.insert('hasOwnProperty', 29);
  map.insert('prototype', 31);
  map.insert('김치', 37);

  expectTrue(map.contains(''));
  expectTrue(map.contains('_'));
  expectTrue(map.contains('constructor'));
  expectTrue(map.contains('hasOwnProperty'));
  expectTrue(map.contains('prototype'));
  expectTrue(map.contains('김치'));

  expectThat(function() { map.get('queso') },
             throwsError(/Unknown key.*queso/));

  var elements = map.getKeys();
  expectThat(elements, elementsAre([_, _, _, _, _, _]));
  expectThat(elements, contains(''));
  expectThat(elements, contains('_'));
  expectThat(elements, contains('constructor'));
  expectThat(elements, contains('hasOwnProperty'));
  expectThat(elements, contains('prototype'));
  expectThat(elements, contains('김치'));

  expectEq(17, map.get(''));
  expectEq(19, map.get('_'));
  expectEq(23, map.get('constructor'));
  expectEq(29, map.get('hasOwnProperty'));
  expectEq(31, map.get('prototype'));
  expectEq(37, map.get('김치'));
};
